package de.rj.urwalking.data.survey;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Iterator;

import org.simpleframework.xml.Element;
import org.simpleframework.xml.Root;

import android.util.Log;

import com.threed.jpct.Matrix;

import de.rj.urwalking.config.Config;
import de.rj.urwalking.config.Constants;
import de.rj.urwalking.db.DBSalientObject;
import de.rj.urwalking.util.UtilMatrix;

/**
 * 
 * A SalientObjectSurvey adds some functionality to a basic {@link Survey}. For example, there is an optional
 * "orientation check" at the beginning.
 * 
 * @author rjj
 * 
 */
@Root(name = "urw_participants_survey", strict = false)
public class SalientObjectSurvey extends Survey implements Serializable {

	private static final long serialVersionUID = 1L;
	private float mOrientation = Float.NaN;
	@Element(name = "urw_urw_salient_object")
	private DBSalientObject referencedObject;
	@Element(name = "urw_current_orientation.timestampend")
	private long endTimestamp;
	@Element(name = "urw_current_orientation.timestampbegin")
	private long startTimestamp;
	private Matrix projectionMatrix;
	/**
	 * utilMatrix is set to projectionMatrix; used for serialization purposes only.
	 * 
	 * @author: mka
	 */
	@Element(name = "urw_projection_matrix")
	private UtilMatrix utilMatrix;
	@Element(name = "iscomplete")
	private boolean isCompleted = false;
	private int surveyType;
	@Element(name = "urw_current_orientation.currentlon")
	private double mLongitude;
	@Element(name = "urw_current_orientation.currentlat")
	private double mLatitude;

	public SalientObjectSurvey(ArrayList<Question> questions, int surveyType) {
		super(questions);
		this.surveyType = surveyType;

		prepareQuestions();
	}

	private void prepareQuestions() {

		// use an Iterator instead of a foreach loop to be able to manipulate the ArrayList
		for (Iterator<Question> it = questions.iterator(); it.hasNext();) {
			Question q = (Question) it.next();

			// tell CategoryQuestion if indoor or outdoor
			if (q instanceof CategoryQuestion) {
				((CategoryQuestion) q).setSurveyType(surveyType);
			}

			// Remove HeaderQuestions (refscale = 13) from questions ArrayList so they don't show up in the XML/DB.
			// Since they were already reorganized in the questionScreens HashMap, they still be shown to the user.
			if (q instanceof HeaderQuestion) {
				it.remove();
			}

		}

	}

	public double getLatitude() {
		return mLatitude;
	}

	public double getLongitude() {
		return mLongitude;
	}

	public float getOrientation() {
		return mOrientation;
	}

	public boolean isCompleted() {
		return isCompleted;
	}

	public void setCompleted(boolean isCompleted) {
		this.isCompleted = isCompleted;
	}

	/**
	 * Increases the screen counter.
	 */
	@Override
	public void nextScreen() {
		screenHistory.add(getCurrentScreenNr() + 1);
	}

	/**
	 * Removes the last item from the screen history when going back a screen.
	 */
	public void previousScreen() {
		screenHistory.remove(screenHistory.size() - 1);
	}

	public void setLocation(double latitude, double longitude) {
		mLatitude = latitude;
		mLongitude = longitude;
	}

	public void setOrientation(float orientation) {
		this.mOrientation = orientation;
	}

	public void setReferencedObject(DBSalientObject referencedObject) {
		this.referencedObject = referencedObject;
	}

	public DBSalientObject getReferencedObject() {
		return referencedObject;
	}

	public void setEndTimestamp(long endTimestamp) {

		this.endTimestamp = endTimestamp;
	}

	public void setStartTimestamp(long startTimestamp) {
		this.startTimestamp = startTimestamp;
	}

	public long getEndTimestamp() {
		return endTimestamp;
	}

	public long getStartTimestamp() {
		return startTimestamp;
	}

	public Matrix getProjectionMatrix() {
		return projectionMatrix;
	}

	public void setProjectionMatrix(Matrix projectionMatrix) {
		this.projectionMatrix = projectionMatrix;
		if (projectionMatrix == null) return; // TODO
		// call setter to create the utility matrix for the sake of serialization
		setUtilMatrix(projectionMatrix);
	}

	public UtilMatrix getUtilMatrix() {
		return utilMatrix;
	}

	/**
	 * Saves the projectionMatrix as UtilMatrix-object.
	 * 
	 * @param projectionMatrix
	 */
	public void setUtilMatrix(Matrix projectionMatrix) {
		this.utilMatrix = new UtilMatrix(projectionMatrix);
	}

	public int getStatus() {

		if (isCompleted) {
			return Config.STATUS_FINISHED;
		} else {
			return Config.STATUS_CANCELLED;
		}
	}

	public void finish() {

		for (Question q : questions) {
			// save the name of the referenced object
			if ((q.getId() == Config.QUESTION_ID_NAME || q.getId() == Config.QUESTION_ID_NAME2)
					&& q instanceof FreeTextQuestion) {

				if (q.getAnswer().getTextAnswer().equals(Constants.EMPTY_STRING)) {
					((FreeTextQuestion) q).forceAnswerSave();
				}
				referencedObject.setName(q.getAnswer().getTextAnswer());
				Log.d(Config.TAG, "set name to " + q.getAnswer().getTextAnswer());
			}
		}

		setCompleted(true);
	}
}
